﻿using System.Collections.Generic;
using System.Diagnostics;
using BSDS.Commands.Commands;
using BSDS.Commands.Commands.Creation;
using BSDS.Commands.Commands.Creation.Implementation;
using BSDS.Commands.Commands.Creation.Implementation.Jobs;
using BSDS.Commands.Configuration;
using BSDS.Commands.Mailing;
using BSDS.Core.Data.Local;
using BSDS.Core.Intialization;

namespace BSDS.Commands.Initalization
{
    public class CommandsModule
    {
        public CommandDispatcher Build(BsdsServicesLocator services)
        {
            return Build(services, new List<ICommandCreatorOverride>());
        }

        public CommandDispatcher Build(BsdsServicesLocator services, IEnumerable<ICommandCreatorOverride> overrides)
        {
            var logger = services.LoggerFactory.Create("Commands", new TraceSource("BSDS.Commands"));
            
            var commandFactory = new CommandFactory(
                new List<ICommandCreator>(new ICommandCreator[]
                {
                    new NoParametersCommandCreator(),
                    new GeocodeCommandCreator(services.GeoService, services.AccountService, services.DataRepository, services.JobRepository, 
                        services.JobService, services.UploadService, logger),
                    new UploadCommandCreator(services.UploadService, services.AccountService, services.JobRepository, 
                        services.JobService, logger, services.DataRepository),
                    new DownloadCommandCreator(services.DownloadService, services.JobService, 
                        services.JobRepository, services.DataRepository), 
                    new ListCommandCreator(services.AccountService),
                    new ConvertToXmlCommandCreator(services.DataRepository, logger),
                    new DeleteCommandCreator(services.AccountService),
                    new SchemaCommandCreator(services.AccountService, logger),
                    new CheckJobsCommandCreator(services.JobRepository, services.JobService),
                    new CheckJobCommandCreator(services.JobService),
                    new CleanJobsCommandCreator(services.JobRepository, services.GeoService, services.UploadService, services.DownloadService), 
                    new WaitJobCommandCreator(services.JobRepository, services.GeoService, services.UploadService, services.DownloadService,
                        services.JobService), 
                    new HelpCommandCreator()
                }));

            foreach (var commandOverride in overrides)
            {
                commandFactory.OverrideCommandCreator(commandOverride.OverridenType, 
                    commandOverride.GetCommandCreatorOverride(services, logger));
            }
            
            var dispatcher = new CommandDispatcher(commandFactory, logger);

            InitializeMailing(services, dispatcher);

            return dispatcher;
        }

        private static void InitializeMailing(BsdsServicesLocator services, CommandDispatcher dispatcher)
        {
            var configuration = new MailingConfigurationLoader().Load();

            if (configuration.NotificationsEnabled)
            {
                var mailingLogCollection = new MailingLogCollection();
                services.LoggerFactory.AddDefaultLogConsumer(mailingLogCollection);

                var mailLogger = services.LoggerFactory.Create("BSDS.Commands.Mailing");
                var mailSender = new MailSender(configuration.Recipients, configuration.SmtpConfiguration, mailLogger);
                var mailBuilder = new MailBuilder(mailingLogCollection, mailSender, configuration.MailSubjectTemplates);
                mailBuilder.RegisterForNotificatons(dispatcher);
            }
        }
    }
}
